/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.fjsei.yewu.device;

import com.querydsl.core.BooleanBuilder;
import graphql.relay.Connection;
import graphql.schema.DataFetchingEnvironment;
import md.cm.geography.Adminunit;
import md.cm.geography.AdminunitRepository;
import md.cm.geography.Village;
import md.cm.geography.VillageRepository;
import md.cm.unit.Division;
import md.cm.unit.Unit;
import md.specialEqp.*;
import md.specialEqp.type.*;
import org.fjsei.yewu.graphql.DbPageConnection;
import org.fjsei.yewu.input.DeviceCommonInput;
import org.fjsei.yewu.jpa.PageOffsetFirst;
import org.fjsei.yewu.resolver.Comngrql;
import org.fjsei.yewu.util.Tool;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.graphql.execution.BatchLoaderRegistry;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.util.List;
import java.util.UUID;

/**默认Unit模型的属性； graphQL接口;
 * 底下批处理方案还不是一种的。 注释掉的也是1个方案。
 * 每一个graphQL的Object对象type都需单独声明一个XxxController implements IdMapper<type> {} 否则Id都无法转换成Relay要的GlobalID的。
 * 报错：无法使用 implements IdMapper<Eqp>
 * */

@Controller
public class EqpController extends Comngrql {
	@PersistenceContext(unitName = "entityManagerFactorySei")
	private EntityManager emSei;
	private final Equipments equipments;
	private final AdminunitRepository adminunitRepository;
	private final VillageRepository villageRepository;
	private final PipingUnitRepository pipingUnitRepository;

	public EqpController(BatchLoaderRegistry registry, Equipments equipments, AdminunitRepository adminunitRepository, VillageRepository villageRepository, PipingUnitRepository pipingUnitRepository) {
		this.equipments = equipments;
		this.adminunitRepository = adminunitRepository;
		this.villageRepository = villageRepository;
		this.pipingUnitRepository = pipingUnitRepository;
	}
	/**因为这个EqpController特殊，无法使用implements IdMapper<Eqp>，只能手动加：
	 * */
//	@SchemaMapping(typeName="Eqp", field="id" )
//	public String getId(Eqp typeObj , DataFetchingEnvironment env) {
//		return Tool.toGlobalId("Eqp", typeObj.getId());
//	}

	//优先级不够：没有进入这里运行？
	@SchemaMapping(typeName="Equipment", field="id" )
	public String getId(Eqp typeObj , DataFetchingEnvironment env) {
		return Tool.toGlobalId("Eqp", typeObj.getId());
	}
	//设置基本设备信息; 参数和模型定义的同名接口的输入类型按顺序一致，否则Two different classes used for type
	/**输入字段放入 DeviceCommonInput 各个设备种类 扁平化。
	 * 少数关键字段不可以经过这个接口修改的。@version需要额外控制的！
	 */
	@MutationMapping
	@Transactional
	public Equipment buildEQP(@Argument String id, @Argument("owner") Long ownerId, @Argument DeviceCommonInput in) {
		Tool.ResolvedGuuid glId= Tool.fromGluuId(id);
		Eqp eQP = equipments.findById(glId.getId()).orElse(null);
		Assert.isTrue(eQP != null,"未找到eQP:"+id);
		//修改数据的特别权限控制嵌入这里：
		//Unit ownerUnit= unitRepository.findById(ownerId).orElse(null);
		//Assert.isTrue(ownerUnit != null,"未找到ownerUnit:"+ownerUnit);
		//eQP.setOwner(ownerUnit);
		String type=in.getType();
		Eqp.EqpBuilder<?, ?>  eqpBld=null;
		if(type.equals("3")) {
			eqpBld = ((Elevator) eQP).toBuilder().oldb(in.getOldb()).flo(in.getFlo());
			((Elevator.ElevatorBuilder<?, ?>) eqpBld).cpm(in.getCpm()).spec(in.getSpec()).nnor(in.getNnor()).vl(in.getVl())
					.hlf(in.getHlf()).lesc(in.getLesc()).wesc(in.getWesc()).tm(in.getTm()).mtm(in.getMtm()).buff(in.getBuff()).rtl(in.getRtl())
					.aap(in.getAap()).prot(in.getProt()).doop(in.getDoop()).limm(in.getLimm()).opm(in.getOpm()).lbkd(in.getLbkd()).nbkd(in.getNbkd());
		}
		else if(type.equals("1")) {
			eqpBld = ((Boiler) eQP).toBuilder().wall(in.getWall()).power(in.getPower());
			((Boiler.BoilerBuilder<?, ?>) eqpBld).form(in.getForm()).fuel(in.getFuel()).pres(in.getPres()).bmod(in.getBmod())
					.asemb(in.getAsemb());
		}
		else if(type.equals("4")) {
			eqpBld = ((Crane) eQP).toBuilder().nnor(in.getNnor()).rtlf(in.getRtlf()).cap(in.getCap()).vls(in.getVls()).rvl(in.getRvl()).mvl(in.getMvl())
					.cvl(in.getCvl()).scv(in.getScv()).lmv(in.getLmv()).rtv(in.getRtv()).luff(in.getLuff()).ns(in.getNs()).flo(in.getFlo()).pnum(in.getPnum())
					.hlf(in.getHlf()).hlfm(in.getHlfm()).rang(in.getRang()).span(in.getSpan()).two(in.getTwo()).twoc(in.getTwoc()).grab(in.getGrab()).suck(in.getSuck())
					.cotr(in.getCotr()).walk(in.getWalk()).mom(in.getMom()).whole(in.getWhole()).tm(in.getTm()).tno(in.getTno()).cpm(in.getCpm())
					.cpi(in.getCpi()).pcs(in.getPcs()).pcw(in.getPcw()).miot(in.getMiot()).opm(in.getOpm()).luf(in.getLuf()).jobl(in.getJobl())
					.highs(in.getHighs()).part(in.getPart()).occa(in.getOcca()).metl(in.getMetl()).auxh(in.getAuxh()).wjib(in.getWjib());
		}
		else if(type.equals("2") || type.equals("R")){
			eqpBld = ((Vessel)eQP).toBuilder().vol(in.getVol()).prs(in.getPrs()).pnum(in.getPnum()).highs(in.getHighs()).weig(in.getWeig())
					.rtlf(in.getRtlf()).fulw(in.getFulw()).mdi(in.getMdi()).jakm(in.getJakm())
					.form(in.getForm()).insul(in.getInsul()).mont(in.getMont());
		}
		else if(type.equals("5")) {
			eqpBld = ((FactoryVehicle) eQP).toBuilder().rtlf(in.getRtlf()).mtm(in.getMtm()).pow(in.getPow());
		}
		else if(type.equals("6")) {
			eqpBld = ((Amusement) eQP).toBuilder().mbig(in.getMbig()).leng(in.getLeng()).high(in.getHigh()).hlf(in.getHlf())
					.pnum(in.getPnum()).vl(in.getVl()).sdia(in.getSdia()).grad(in.getGrad()).angl(in.getAngl());
		}
		else if(type.equals("8")) {
			eqpBld = ((Pipeline) eQP).toBuilder().matr(in.getMatr()).mdi(in.getMdi()).prs(in.getPrs())
					.temp(in.getTemp());
		}
		else
			eqpBld = eQP.toBuilder();
		//公共部分的:
		Unit unitMakeu=fromInputUnitGlobalID(in.getMakeu());
		Unit unitOwner=fromInputUnitGlobalID(in.getOwner());
		Unit unitRemu=fromInputUnitGlobalID(in.getRemu());
		Unit unitRepu=fromInputUnitGlobalID(in.getRepu());
		Unit unitInsu=fromInputUnitGlobalID(in.getInsu());
		Unit unitMtu;   //维保部门决定了维保单位
		//Division diviMtud=fromInputDivisionGlobalID(in.getMtud(),true);
		//if(null!=diviMtud)  unitMtu=diviMtud.getUnit();
		unitMtu=fromInputUnitGlobalID(in.getMtu());
		Unit unitIspu=fromInputUnitGlobalID(in.getIspu());
		Unit unitUseu;
		Division diviUsud=fromInputDivisionGlobalID(in.getUsud(),false);
		if(null!=diviUsud)  unitUseu=diviUsud.getUnit();
		else    unitUseu=fromInputUnitGlobalID(in.getUseu());
/*        //test::
        if(unitUseu.getDvs().size()<25) {
            Division devision = new Division();
            devision.setName("test it--" + in.getUsud());
            devision.setUnit(unitUseu);
            divisionRepository.saveAndFlush(devision);
            Set<Division> diviss=new HashSet<>();
            diviss.add(devision);
            unitUseu.setDvs(diviss);
            unitRepository.saveAndFlush(unitUseu);
        }*/
		Adminunit adminunit=null;
		if(StringUtils.hasText(in.getAd())) {
			glId = Tool.fromGluuId(in.getAd());
			adminunit = adminunitRepository.findById(glId.getId()).orElse(null);
			Assert.isTrue(adminunit != null, "未找到Adminunit:" + in.getAd());
		}
		Village village=null;
		if(StringUtils.hasText(in.getVlg())) {   //前端给我：{id=VmlsbGFnZTozODE4, name=晋安区光明港湾}
			glId = Tool.fromGluuId(in.getVlg());
			village = villageRepository.findById(glId.getId()).orElse(null);
			Assert.isTrue(village != null, "未找到village:" + in.getVlg());
		}
		Double latval= StringUtils.hasText(in.getLat())? Double.valueOf(in.getLat()) : null;
		Double lonval= StringUtils.hasText(in.getLon())? Double.valueOf(in.getLon()) : null;
		eQP=eqpBld.cod(in.getCod()).reg(RegState_Enum.values()[0])
				.ust(UseState_Enum.USE)
				.svp(in.getSvp()).pa(in.getPa())
				.cpa(in.getCpa()).vital(in.getVital()).level(in.getLevel()).titl(in.getTitl()).lpho(in.getLpho()).plat(in.getPlat())
				.used(in.getUsed()).expire(in.getExpire()).move(in.getMove()).money(in.getMoney()).impt(in.getImpt())
				.model(in.getModel()).fno(in.getFno()).plno(in.getPlno()).mkd(in.getMkd()).makeu(unitMakeu).sno(in.getSno())
				.owner(unitOwner).remu(unitRemu).repu(unitRepu).insu(unitInsu).mtu(unitMtu).ispu(unitIspu)
				.useu(unitUseu).usud(diviUsud).ad(adminunit).vlg(village).address(in.getAddress()).insd(in.getInsd())
				.lat(latval).lon(lonval).plcls(in.getPlcls()).dense(in.getDense()).seimp(in.getSeimp())
				.version(in.getVersion())
				.build();

		equipments.save(eQP);
		return (Equipment) eQP;
	}
}

